package test.yzx.pproject.util;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.FrameLayout;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * same as {@link android.widget.ExpandableListView}, but only the group view is stay at top
 */
public class StickyExpandableListLayout extends FrameLayout {

    public StickyExpandableListLayout(Context context) {
        super(context);
        init();
    }
    public StickyExpandableListLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public StickyExpandableListLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }
    /* add ExpandableListView and set scroll event*/
    private void init(){
        mRealStickyExpandableListView = new RealStickyExpandableListView(getContext());
        mRealStickyExpandableListView.setGroupIndicator(null);
        addView(mRealStickyExpandableListView,new ViewGroup.LayoutParams(-1, -1));
        stickyHeaderContainer = new FrameLayout(getContext());
        addView(stickyHeaderContainer,new ViewGroup.LayoutParams(-1, -2));
        mRealStickyExpandableListView.addOnScrollListener(new SimpleOnScrollListenerList() {
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                if(view.getCount()==0) return ;
                doOnScroll(firstVisibleItem, visibleItemCount);
            }
        });
    }

    private HashMap<Integer,View> copyStickyHeaderViewCache = new HashMap<>();
    private RealStickyExpandableListView mRealStickyExpandableListView;
    private FrameLayout stickyHeaderContainer;

    /** get inside ExpandableListView */
    public RealStickyExpandableListView getReal() {
        return mRealStickyExpandableListView;
    }

    /*  */
    private void doOnScroll(int firstVisibleItem, int visibleItemCount){
        RealStickyExpandableListView listview = mRealStickyExpandableListView;
        if(!listview.useStickyAdapter) {
            if(stickyHeaderContainer.getChildCount() > 0)
                stickyHeaderContainer.removeAllViews();
            return ;
        }
        StickyExpandableListAdapter adapter = (StickyExpandableListAdapter)mRealStickyExpandableListView.mAdapter;
        if(adapter==null || adapter.isEmpty())
            return ;
        int groupPosition = adapter.getGroupPositionByPosition(firstVisibleItem, listview);
        if(groupPosition<0){
            resetStickyheaderContainer();
            return ;
        }
        if(!listview.isGroupExpanded(groupPosition)){
            resetStickyheaderContainer();
            return ;
        }
        View stickyGroupView = getCopyStickyGroupView(adapter, groupPosition);
        if(stickyHeaderContainer.getChildCount()==0 || stickyHeaderContainer.getChildAt(0) != stickyGroupView){
            stickyHeaderContainer.removeAllViews();
            stickyHeaderContainer.addView(stickyGroupView);
        }
        FirstHeaderViewInfo info = getFirstHeaderView(adapter, firstVisibleItem, visibleItemCount);
        if(info == null){
            stickyHeaderContainer.setTranslationY(0);
            return ;
        }
        if(info.groupPosition == groupPosition){
            stickyHeaderContainer.setTranslationY(0);
            return ;
        }
        int firstGroupViewTop = info.view.getTop();
        int currentStickyHeight = stickyHeaderContainer.getHeight();
        if(firstGroupViewTop>currentStickyHeight){
            stickyHeaderContainer.setTranslationY(0);
        }else
            stickyHeaderContainer.setTranslationY(firstGroupViewTop - currentStickyHeight);
        checkStickyHeaderChildHeight();
    }

    /* only in order to fix a bug */
    private void checkStickyHeaderChildHeight(){
        View child = stickyHeaderContainer.getChildAt(0);
        if(stickyHeaderContainer.getHeight() != 0 && child.getHeight()==0)
            child.requestLayout();
    }
    /*  */
    private void resetStickyheaderContainer(){
        if(stickyHeaderContainer.getChildCount() > 0)
            stickyHeaderContainer.removeAllViews();
        stickyHeaderContainer.setTranslationY(0);
    }
    /*  */
    private View getCopyStickyGroupView(StickyExpandableListAdapter adapter, int groupPosition){
        View cacheView = copyStickyHeaderViewCache.get(groupPosition);
        if(cacheView==null) {
            cacheView = adapter.getCopyGroupView(groupPosition);
            if(cacheView==null)
                throw new IllegalStateException("sticky group view can not be null");
            copyStickyHeaderViewCache.put(groupPosition, cacheView);
        }
        return cacheView;
    }
    /* get the first header view and position in listview */
    private final class FirstHeaderViewInfo{int groupPosition;View view;}
    private final FirstHeaderViewInfo firstHeaderViewInfo = new FirstHeaderViewInfo();
    private FirstHeaderViewInfo getFirstHeaderView(StickyExpandableListAdapter adapter, int firstVisiblePosition, int visibleItemCount){
        for(int i = firstVisiblePosition, end = firstVisiblePosition + visibleItemCount; i<end; i++)
            if(adapter.isGroupViewType(i, mRealStickyExpandableListView)){
                firstHeaderViewInfo.groupPosition = adapter.getGroupPositionByPosition(i, mRealStickyExpandableListView);
                firstHeaderViewInfo.view = mRealStickyExpandableListView.getChildAt(i - firstVisiblePosition);
                return firstHeaderViewInfo;
            }
        return null;
    }


    /* ==== $-$ ==== */


    public static class RealStickyExpandableListView extends ExpandableListView{
        public RealStickyExpandableListView(Context context) {
            super(context);
            setOnScrollListener(mOnScrollListener);
        }
        /* a listener for all listener */
        private final OnScrollListener mOnScrollListener = new OnScrollListener() {
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                for (OnScrollListener item : mOnScrollListenerList)
                    item.onScrollStateChanged(view, scrollState);
            }
            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
                for (OnScrollListener item : mOnScrollListenerList)
                    item.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
            }
        };

        @Override
        public final void setOnScrollListener(OnScrollListener l) {
            if(l != mOnScrollListener)
                throw new IllegalStateException("--use addOnScrollListener instead--");
            super.setOnScrollListener(l);
        }

        private List<OnScrollListener> mOnScrollListenerList = new ArrayList<>(0);

        public void addOnScrollListener(OnScrollListener l){
            if(mOnScrollListenerList.contains(l)) return ;
            mOnScrollListenerList.add(l);
        }

        private ExpandableListAdapter mAdapter;
        private boolean useStickyAdapter;

        @Override
        public void setAdapter(ExpandableListAdapter adapter) {
            super.setAdapter(adapter);
            this.mAdapter = adapter;
            useStickyAdapter = adapter instanceof StickyExpandableListAdapter;
            /// when set new adapter, reset sticky header ///
            ((StickyExpandableListLayout) getParent()).resetStickyheaderContainer();
        }
        /**  */
        public void expandAllGroup(){
            if(mAdapter==null || mAdapter.isEmpty())
                return ;
            for (int i = 0; i < mAdapter.getGroupCount(); i++)
                expandGroup(i, false);
        }
        /**  */
        public void collapseAllGroup(){
            if(mAdapter==null || mAdapter.isEmpty())
                return ;
            for (int i = 0; i < mAdapter.getGroupCount(); i++)
                collapseGroup(i);
        }
        /**  */
        public void toggle(int groupPosition, boolean anim){
            if(isGroupExpanded(groupPosition))
                collapseGroup(groupPosition);
            else
                expandGroup(groupPosition, anim);
        }
    }


    /* ==== $-$ ==== */


    private class SimpleOnScrollListenerList implements AbsListView.OnScrollListener {
        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        }
    }

}
